package com.tbit.main.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.MachineOpLog;
import com.tbit.main.constant.MachineStateConstant;
import com.tbit.main.constant.MapConstant;
import com.tbit.main.constant.RecoveryLogConstant;
import com.tbit.main.dao.log.RecoveryLogMapper;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.VO.RecoveryLogStat;
import com.tbit.main.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: chen
 * @Description: 车辆回收记录
 * @Date: 创建于 15:23 2023/2/9
 */
@Service
public class RecoveryLogServiceImpl extends ServiceImpl<RecoveryLogMapper, RecoveryLog> implements
        RecoveryLogService {

    @Autowired
    private RecoveryLogMapper recoveryLogMapper;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private StockMachineService stockMachineService;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private MachineOpLogService machineOpLogService;

    @Override
    public void add(String userCode, AccountUser accountUser) {
        Machine machine = machineService.getByUseCode(userCode);
        if (machine == null) {
            throw new BaseException("Machine.notExist");
        }
        /**设备权限判断*/
        machineService.auth(accountUser.getAgents(), machine);
        if (!machine.getState().equals(MachineStateConstant.MACHINE_STATE_GZ)) {
            throw new BaseException("Machine.not.fault");
        }
        /**判断是否入库*/
        List<Integer> machineIds = new LinkedList<>();
        machineIds.add(machine.getMachineId());
        List<Integer> stockMachineIds = stockMachineService.getAccountIdByMachineId(machine.getAccountId(), machineIds);
        if (stockMachineIds != null && !stockMachineIds.isEmpty()) {
            throw new BaseException("StockMachine.is.operate");
        }

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("machineId", machine.getMachineId());
        queryWrapper.eq("state", RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
        RecoveryLog recoveryLogDB = getOne(queryWrapper);
        if (recoveryLogDB != null) {
            throw new BaseException("recovery.is.exist");
        }

        MachineStatus machineStatus = machineStatusService.getByMachineId(machine.getMachineId());
        if (machineStatus != null && machineStatus.getLon() != null && machineStatus.getLat() != null) {
            RecoveryLog recoveryLog = new RecoveryLog(machine.getAccountId(), machine.getMachineId(), machine.getUserCode(), machine.getMachineNO()
                    , new Date(), machineStatus.getLon(), machineStatus.getLat(), accountUser.getAccountUserId(), accountUser.getName(),
                    RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
            save(recoveryLog);

            // 插入车辆操作日志
            machineOpLogService.insertSingle(MachineOpLog.builder()
                    .accountId(recoveryLog.getAccountId())
                    .machineId(recoveryLog.getMachineId())
                    .machineNO(recoveryLog.getMachineNO())
                    .userCode(recoveryLog.getUserCode())
                    .operation("回收")
                    .opUser(accountUser.getName())
                    .opUserPhone(accountUser.getPhone())
                    .opPlatform(OperationPlatform.MAINTAIN.code)
                    .result(true)
                    .opTime(LocalDateTime.now())
                    .build()
            );
        }
    }

    @Override
    public List<RecoveryLogStat> getUserRecoveryLogNum(Integer accountId, Long startTime,
                                                       Long endTime) {
        Map<String, Object> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("startTime", new Date(startTime));
        map.put("endTime", new Date(endTime));
        return recoveryLogMapper.getByAccountIdTime(map);
    }

    @Override
    public Page<RecoveryLog> queryPage(Integer accountUserId, Integer accountId, Long startTime, Long endTime,
                                       Integer pageNO, Integer rowCount, Integer mapType) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("accountId", accountId);
        queryWrapper.eq("recoveryUserId", accountUserId);
        queryWrapper.ge("endTime", new Date(startTime));
        queryWrapper.le("endTime", new Date(endTime));
        queryWrapper.orderByDesc("recoveryId");
        Page<RecoveryLog> page = Page.of(pageNO, rowCount);
        page(page, queryWrapper);
        List<RecoveryLog> logs = page.getRecords();
        for (RecoveryLog r : logs) {
            Point startPoint = calibrateService.commonCalibrate(new Point(r.getStartLo(), r.getStartLa()), MapConstant.MAP_ORI, mapType);
            r.setStartLo(startPoint.getX());
            r.setStartLa(startPoint.getY());
            Point endPoint = calibrateService.commonCalibrate(new Point(r.getEndLo(), r.getEndLa()), MapConstant.MAP_ORI, mapType);
            r.setEndLo(endPoint.getX());
            r.setEndLa(endPoint.getY());
        }
        page.setSize(count(queryWrapper));
        return page;
    }

    @Override
    public void del(String userCode, AccountUser accountUser) {
        Machine machine = machineService.getByUseCode(userCode);
        if (machine == null) {
            throw new BaseException("Machine.notExist");
        }
        machineService.auth(accountUser.getAgents(), machine);
        RecoveryLog recoveryLog = getByAccountId(machine.getAccountId(), machine.getMachineId(), RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
        if (recoveryLog != null) {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("recoveryId", recoveryLog.getRecoveryId());
            recoveryLogMapper.delete(queryWrapper);
        }
    }

    @Override
    public RecoveryLog getByAccountId(Integer accountId, Integer machineId, Integer state) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("accountId", accountId);
        queryWrapper.eq("machineId", machineId);
        queryWrapper.eq("state", state);
        RecoveryLog recoveryLog = getOne(queryWrapper);
        return recoveryLog;
    }

    @Override
    public void addBatch(List<String> userCodes, AccountUser accountUser) {
        List<Machine> machines = machineService.getByUserCodes(userCodes);
        /**批量校验*/
        stockMachineService.checkBatch(machines, accountUser, userCodes);
        Boolean result = machines.stream().allMatch(machine -> machine.getState().equals(MachineStateConstant.MACHINE_STATE_GZ));
        if (!result) {
            throw new BaseException("Machine.not.fault");
        }
        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("machineId", machineIds);
        List<RecoveryLog> recoveryLogList = list(queryWrapper);
        if (recoveryLogList != null && !recoveryLogList.isEmpty()) {
            throw new BaseException("recovery.is.exist");
        }

        /**获取状态*/
        List<MachineStatus> list = machineStatusService.getByMachineIdBatch(machineIds);
        Map<Integer, Machine> map = machines.stream().collect(Collectors.toMap(Machine::getMachineId, p -> p));

        List<RecoveryLog> recoveryLogs = new ArrayList<>();
        list.stream().forEach(machineStatus -> {
            RecoveryLog recoveryLog = new RecoveryLog(map.get(machineStatus.getMachineId()).getAccountId(), machineStatus.getMachineId(), map.get(machineStatus.getMachineId()).getUserCode(), map.get(machineStatus.getMachineId()).getMachineNO()
                    , new Date(), machineStatus.getLon(), machineStatus.getLat(), accountUser.getAccountUserId(), accountUser.getName(),
                    RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
            recoveryLogs.add(recoveryLog);
        });
        saveBatch(recoveryLogs);

        // 插入车辆操作日志
        List<MachineOpLog> opLogs = recoveryLogs.stream()
                .map(recoveryLog -> MachineOpLog.builder()
                        .accountId(recoveryLog.getAccountId())
                        .machineId(recoveryLog.getMachineId())
                        .machineNO(recoveryLog.getMachineNO())
                        .userCode(recoveryLog.getUserCode())
                        .operation("回收")
                        .opUser(accountUser.getName())
                        .opUserPhone(accountUser.getPhone())
                        .opPlatform(OperationPlatform.MAINTAIN.code)
                        .result(true)
                        .opTime(LocalDateTime.now())
                        .build()
                )
                .collect(Collectors.toList());
        machineOpLogService.insertBatch(opLogs);
    }

    @Override
    public void delBatch(List<String> userCodes, AccountUser accountUser) {
        List<Machine> machines = machineService.getByUserCodes(userCodes);
        /**批量校验*/
        stockMachineService.checkBatch(machines, accountUser, userCodes);
        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("accountId", machines.get(0).getAccountId());
        queryWrapper.in("machineId", machineIds);
        queryWrapper.eq("state", RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
        remove(queryWrapper);
    }

    @Override
    public List<String> getByUserCode(String userCode, AccountUser accountUser,Integer accountId) {
        Machine machine = machineService.getByUseCodeAndAccountId(userCode,accountId);
        if (machine == null) {
            throw new BaseException("Machine.notExist");
        }
        machineService.auth(accountUser.getAgents(), machine.getMachineId());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("state", RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
        queryWrapper.eq("machineId", machine.getMachineId());
        RecoveryLog recoveryLog = getOne(queryWrapper);
        if (recoveryLog == null) {
            return new ArrayList<>();
        }
        QueryWrapper listWrapper = new QueryWrapper();
        listWrapper.eq("recoveryUserId", recoveryLog.getRecoveryUserId());
        listWrapper.eq("state", RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
        List<RecoveryLog> recoveryLogs = list(listWrapper);
        return recoveryLogs.stream().map(RecoveryLog::getUserCode).collect(Collectors.toList());
    }

    @Override
    public void updateBatchByMachineList(List<Integer> machineIdList, Integer state, String remark) {
        recoveryLogMapper.updateBatchByMachineList(machineIdList, state, remark);
    }
}
